package cn.turboinfo.dongying.api.provider.common.service.impl.policy;

import cn.turboinfo.dongying.api.domain.common.service.policy.PolicyService;
import cn.turboinfo.dongying.api.entity.common.enumeration.policy.PolicyType;
import cn.turboinfo.dongying.api.entity.common.exception.policy.PolicyException;
import cn.turboinfo.dongying.api.entity.common.pojo.policy.Policy;
import cn.turboinfo.dongying.api.entity.common.pojo.policy.PolicyCreator;
import cn.turboinfo.dongying.api.entity.common.pojo.policy.PolicyUpdater;
import cn.turboinfo.dongying.api.provider.common.repository.database.policy.PolicyDAO;
import cn.turboinfo.dongying.api.provider.common.repository.database.policy.PolicyPO;
import lombok.RequiredArgsConstructor;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;

@RequiredArgsConstructor
@Service
public class PolicyServiceImpl extends AbstractQServiceImpl<Policy> implements PolicyService {
    private final PolicyDAO policyDAO;

    @Override
    public Optional<Policy> getById(Long id) {
        return policyDAO.findById(id).map(this::convertQBean);
    }

    @Override
    public Policy getByIdEnsure(Long id) {
        return getById(id).orElseThrow(this.getExceptionSupplier("未找到数据, id=" + id, null));
    }

    @Override
    public List<Policy> findByIdCollection(Collection<Long> idCollection) {
        return convertStreamQBeanToList(policyDAO.findAllByIdIn(idCollection).stream());
    }

    @Override
    @Transactional
    public Policy save(PolicyCreator creator) throws PolicyException {
        PolicyPO po = new PolicyPO();

        QBeanCreatorHelper.copyCreatorField(po, creator);

        return convertQBean(policyDAO.save(po));
    }

    @Override
    @Transactional
    public Policy update(PolicyUpdater updater) throws PolicyException {
        PolicyPO po = getEntityWithNullCheckForUpdate(updater.getUpdateId(), policyDAO);

        QBeanUpdaterHelper.copyUpdaterField(po, updater);

        return convertQBean(po);
    }

    @Override
    public QResponse<Policy> findAll(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<PolicyPO> findAllInternal(QRequest request, QPage requestPage) {
        return policyDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    @Transactional
    public void deleteById(Long id) throws PolicyException {
        PolicyPO po = getEntityWithNullCheckForUpdate(id, policyDAO);
        po.setDeletedTime(System.currentTimeMillis());
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new PolicyException(message, cause);
    }

    @Override
    public List<Policy> findAllByType(PolicyType policyType) {
        if (policyType == null || policyType == PolicyType.ALL) {
            return convertStreamQBeanToList(StreamSupport.stream(policyDAO.findAll().spliterator(), false));
        } else {
            return convertStreamQBeanToList(policyDAO.findByPolicyTypeOrderByIdAsc(policyType).stream());
        }
    }
}
